package com.shrct.businessprocess.purchase.impl;

import com.google.common.base.Objects;
import com.google.common.collect.Iterables;
import com.shrct.businessprocess.product.RCProductEntry;
import com.shrct.businessprocess.product.RCProductPurchaseInfo;
import com.shrct.businessprocess.product.RCProductSpecification;
import com.shrct.businessprocess.product.impl.RCProductSpecificationImpl;
import com.shrct.businessprocess.project.RCProjectMoney;
import com.shrct.businessprocess.purchase.RCBaseProductPurchaseBudget;
import com.shrct.businessprocess.purchase.RCBudgetContract;
import com.shrct.businessprocess.purchase.RCBudgetContractItem;
import com.shrct.businessprocess.purchase.RCBudgetContractProductItem;
import com.shrct.businessprocess.purchase.RCProductInStockEvent;
import com.shrct.businessprocess.purchase.RCProductPurchaseRequest;
import com.shrct.businessprocess.purchase.RCPurchaseOrder;
import com.shrct.businessprocess.purchase.RCPurchaseOrderItem;
import com.shrct.businessprocess.purchase.impl.RCPurchaseOrderImpl;
import com.shrct.businessprocess.purchase.proxy.RCPurchaseOrderItemProxy;
import edu.fudan.mylang.common.NumberExtensions;
import edu.fudan.mylang.pf.BaseModelObject;
import edu.fudan.mylang.pf.IGenericQuery;
import edu.fudan.mylang.pf.IObjectFactory;
import edu.fudan.mylang.utils.DateUtil;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Set;
import javax.persistence.AssociationOverride;
import javax.persistence.AssociationOverrides;
import javax.persistence.AttributeOverride;
import javax.persistence.AttributeOverrides;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.DiscriminatorColumn;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import org.eclipse.xtext.xbase.lib.Functions.Function1;
import org.eclipse.xtext.xbase.lib.Functions.Function2;
import org.eclipse.xtext.xbase.lib.IterableExtensions;
import org.eclipse.xtext.xbase.lib.Procedures.Procedure1;
import org.eclipse.xtext.xbase.lib.StringExtensions;
import org.hibernate.annotations.DiscriminatorOptions;

@Entity
@DiscriminatorValue("RCPURCHASEORDERITEM_TYPE")
@DiscriminatorOptions(force = true)
@DiscriminatorColumn(length = 64)
@Table(name = "rcpurchaseorderitem")
public class RCPurchaseOrderItemImpl extends BaseModelObject implements RCPurchaseOrderItem {
  public RCPurchaseOrderItemImpl() {
    super();
  }
  
  public RCPurchaseOrderItemImpl(final RCPurchaseOrder purchaseOrder) {
    super();
    this.purchaseOrder = purchaseOrder;
  }
  
  @JoinColumn(name = "purchaseOrder_id")
  @ManyToOne(targetEntity = RCPurchaseOrderImpl.class, cascade = { CascadeType.MERGE, CascadeType.PERSIST })
  private RCPurchaseOrder purchaseOrder;
  
  public RCPurchaseOrder getPurchaseOrder() {
    return this.purchaseOrder;
  }
  
  public RCPurchaseOrderItem setPurchaseOrder(final RCPurchaseOrder purchaseOrder) {
    this.purchaseOrder = purchaseOrder;
    return this;			
    
  }
  
  @JoinColumn(name = "productSpec_id")
  @ManyToOne(targetEntity = RCProductSpecificationImpl.class, cascade = { CascadeType.MERGE, CascadeType.PERSIST })
  private RCProductSpecification productSpec;
  
  public RCProductSpecification getProductSpec() {
    return this.productSpec;
  }
  
  public RCPurchaseOrderItem setProductSpec(final RCProductSpecification productSpec) {
    this.productSpec = productSpec;
    return this;			
    
  }
  
  private Integer quantity;
  
  public Integer getQuantity() {
    return this.quantity;
  }
  
  public RCPurchaseOrderItem setQuantity(final Integer quantity) {
    this.quantity = quantity;
    return this;			
    
  }
  
  private Date expectDate;
  
  public Date getExpectDate() {
    return this.expectDate;
  }
  
  public RCPurchaseOrderItem setExpectDate(final Date expectDate) {
    this.expectDate = expectDate;
    return this;			
    
  }
  
  @Embedded
  @AttributeOverrides(value = { @AttributeOverride(name = "amount", column = @Column(name = "price_amount") ), @AttributeOverride(name = "workaround", column = @Column(name = "price_workaround") ) } )
  @AssociationOverrides(value = @AssociationOverride(name = "exchange", joinColumns = @JoinColumn(name = "price_exchange") ) )
  private RCProjectMoney price = com.shrct.businessprocess.project.RCProjectMoney.create();
  
  public RCProjectMoney getPrice() {
    return this.price;
  }
  
  public RCPurchaseOrderItem setPrice(final RCProjectMoney price) {
    this.price = price;
    return this;			
    
  }
  
  public Integer getTotalAcceptItemsQuantity() {
    int _xblockexpression = (int) 0;
    {
      IGenericQuery<Long> query=getObjectFactory().createGenericQuery(Long.class,"select sum(acceptItem.quantity) from com.shrct.businessprocess.purchase.impl.RCPurchaseOrderAcceptItemImpl as acceptItem   where ((acceptItem.orderItem) = (:this)) and  acceptItem.active = 1      ").setParameter("this",this);
      Long result = query.uniqueResult();
      int _xifexpression = (int) 0;
      boolean _equals = Objects.equal(result, null);
      if (_equals) {
        _xifexpression = 0;
      } else {
        int _intValue = result.intValue();
        _xifexpression = _intValue;
      }
      _xblockexpression = (_xifexpression);
    }
    return Integer.valueOf(_xblockexpression);
  }
  
  public Boolean getIsAllItemsAccepted() {
    Integer _totalAcceptItemsQuantity = this.getTotalAcceptItemsQuantity();
    boolean _greaterEqualsThan = (_totalAcceptItemsQuantity.compareTo(this.quantity) >= 0);
    return Boolean.valueOf(_greaterEqualsThan);
  }
  
  public Boolean getIsExpectDateOverDue() {
    boolean _and = false;
    Date _day = DateUtil.today();
    long _time = _day.getTime();
    long _time_1 = this.expectDate.getTime();
    boolean _greaterThan = (_time > _time_1);
    if (!_greaterThan) {
      _and = false;
    } else {
      Boolean _isAllItemsAccepted = this.getIsAllItemsAccepted();
      boolean _not = (!_isAllItemsAccepted);
      _and = (_greaterThan && _not);
    }
    return Boolean.valueOf(_and);
  }
  
  public Integer getTotalInStockQuantity() {
    int _xblockexpression = (int) 0;
    {
      Collection<RCProductInStockEvent> _inStockEvents = this.getInStockEvents();
      final Function1<RCProductInStockEvent,Integer> _function = new Function1<RCProductInStockEvent,Integer>() {
          public Integer apply(final RCProductInStockEvent it) {
            Integer _quantity = it.getQuantity();
            return _quantity;
          }
        };
      Iterable<Integer> _map = IterableExtensions.<RCProductInStockEvent, Integer>map(_inStockEvents, _function);
      final Function2<Integer,Integer,Integer> _function_1 = new Function2<Integer,Integer,Integer>() {
          public Integer apply(final Integer i1, final Integer i2) {
            int _plus = ((i1).intValue() + (i2).intValue());
            return Integer.valueOf(_plus);
          }
        };
      Integer result = IterableExtensions.<Integer>reduce(_map, _function_1);
      int _xifexpression = (int) 0;
      boolean _equals = Objects.equal(result, null);
      if (_equals) {
        _xifexpression = 0;
      } else {
        _xifexpression = result;
      }
      _xblockexpression = (_xifexpression);
    }
    return Integer.valueOf(_xblockexpression);
  }
  
  public Integer getTotalDeliveredQuantity() {
    IGenericQuery<RCProductPurchaseInfo> query=getObjectFactory().createGenericQuery(RCProductPurchaseInfo.class,"select e from com.shrct.businessprocess.product.impl.RCProductPurchaseInfoImpl as e   where ((e.orderItem) = (:this)) and  e.active = 1      ").setParameter("this",this);
    Collection<RCProductPurchaseInfo> _list = query.list();
    final Function1<RCProductPurchaseInfo,Integer> _function = new Function1<RCProductPurchaseInfo,Integer>() {
        public Integer apply(final RCProductPurchaseInfo it) {
          Integer _deliverQuantity = it.getDeliverQuantity();
          return _deliverQuantity;
        }
      };
    Iterable<Integer> _map = IterableExtensions.<RCProductPurchaseInfo, Integer>map(_list, _function);
    final Function2<Integer,Integer,Integer> _function_1 = new Function2<Integer,Integer,Integer>() {
        public Integer apply(final Integer i1, final Integer i2) {
          int _plus = ((i1).intValue() + (i2).intValue());
          return Integer.valueOf(_plus);
        }
      };
    Integer _reduce = IterableExtensions.<Integer>reduce(_map, _function_1);
    Integer _nullsafe = NumberExtensions.nullsafe(_reduce);
    return _nullsafe;
  }
  
  public Collection<RCProductInStockEvent> getInStockEvents() {
    IGenericQuery<RCProductInStockEvent> query=getObjectFactory().createGenericQuery(RCProductInStockEvent.class,"select e from com.shrct.businessprocess.purchase.impl.RCProductInStockEventImpl as e   where ((e.orderItem) = (:this)) and  e.active = 1      ").setParameter("this",this);
    Collection<RCProductInStockEvent> _list = query.list();
    return _list;
  }
  
  public RCProjectMoney getUnitPrice() {
    int _intValue = this.quantity.intValue();
    RCProjectMoney _div = this.price.div(Double.valueOf(((double) _intValue)));
    return _div;
  }
  
  public Collection<RCBudgetContractProductItem> findBudgetItemCandidates(final String title) {
    RCProductPurchaseRequest _purchaseRequest = this.purchaseOrder.getPurchaseRequest();
    RCBaseProductPurchaseBudget _budget = _purchaseRequest.getBudget();
    Collection<RCBudgetContract> _contracts = _budget.getContracts();
    final Function1<RCBudgetContract,Collection<RCBudgetContractItem>> _function = new Function1<RCBudgetContract,Collection<RCBudgetContractItem>>() {
        public Collection<RCBudgetContractItem> apply(final RCBudgetContract it) {
          Collection<RCBudgetContractItem> _contratItems = it.getContratItems();
          return _contratItems;
        }
      };
    Iterable<Collection<RCBudgetContractItem>> _map = IterableExtensions.<RCBudgetContract, Collection<RCBudgetContractItem>>map(_contracts, _function);
    Iterable<RCBudgetContractItem> _flatten = Iterables.<RCBudgetContractItem>concat(_map);
    Iterable<RCBudgetContractProductItem> _filter = Iterables.<RCBudgetContractProductItem>filter(_flatten, RCBudgetContractProductItem.class);
    final Function1<RCBudgetContractProductItem,Boolean> _function_1 = new Function1<RCBudgetContractProductItem,Boolean>() {
        public Boolean apply(final RCBudgetContractProductItem it) {
          boolean _and = false;
          RCProductSpecification _productSpec = it.getProductSpec();
          boolean _equals = Objects.equal(_productSpec, RCPurchaseOrderItemImpl.this.productSpec);
          if (!_equals) {
            _and = false;
          } else {
            boolean _or = false;
            boolean _and_1 = false;
            boolean _isNullOrEmpty = StringExtensions.isNullOrEmpty(title);
            if (!_isNullOrEmpty) {
              _and_1 = false;
            } else {
              String _title = it.getTitle();
              boolean _isNullOrEmpty_1 = StringExtensions.isNullOrEmpty(_title);
              _and_1 = (_isNullOrEmpty && _isNullOrEmpty_1);
            }
            if (_and_1) {
              _or = true;
            } else {
              String _title_1 = it.getTitle();
              boolean _equals_1 = Objects.equal(title, _title_1);
              _or = (_and_1 || _equals_1);
            }
            _and = (_equals && _or);
          }
          return Boolean.valueOf(_and);
        }
      };
    Iterable<RCBudgetContractProductItem> _filter_1 = IterableExtensions.<RCBudgetContractProductItem>filter(_filter, _function_1);
    Set<RCBudgetContractProductItem> _set = IterableExtensions.<RCBudgetContractProductItem>toSet(_filter_1);
    return _set;
  }
  
  public Collection<RCBudgetContractProductItem> findBudgetItemCandidates() {
    RCProductPurchaseRequest _purchaseRequest = this.purchaseOrder.getPurchaseRequest();
    RCBaseProductPurchaseBudget _budget = _purchaseRequest.getBudget();
    Collection<RCBudgetContract> _contracts = _budget.getContracts();
    final Function1<RCBudgetContract,Collection<RCBudgetContractItem>> _function = new Function1<RCBudgetContract,Collection<RCBudgetContractItem>>() {
        public Collection<RCBudgetContractItem> apply(final RCBudgetContract it) {
          Collection<RCBudgetContractItem> _contratItems = it.getContratItems();
          return _contratItems;
        }
      };
    Iterable<Collection<RCBudgetContractItem>> _map = IterableExtensions.<RCBudgetContract, Collection<RCBudgetContractItem>>map(_contracts, _function);
    Iterable<RCBudgetContractItem> _flatten = Iterables.<RCBudgetContractItem>concat(_map);
    Iterable<RCBudgetContractProductItem> _filter = Iterables.<RCBudgetContractProductItem>filter(_flatten, RCBudgetContractProductItem.class);
    final Function1<RCBudgetContractProductItem,Boolean> _function_1 = new Function1<RCBudgetContractProductItem,Boolean>() {
        public Boolean apply(final RCBudgetContractProductItem it) {
          RCProductSpecification _productSpec = it.getProductSpec();
          boolean _equals = Objects.equal(_productSpec, RCPurchaseOrderItemImpl.this.productSpec);
          return Boolean.valueOf(_equals);
        }
      };
    Iterable<RCBudgetContractProductItem> _filter_1 = IterableExtensions.<RCBudgetContractProductItem>filter(_filter, _function_1);
    Set<RCBudgetContractProductItem> _set = IterableExtensions.<RCBudgetContractProductItem>toSet(_filter_1);
    return _set;
  }
  
  public Collection<RCProductEntry> getAllAcceptedProducts() {
    IGenericQuery<RCProductInStockEvent> query=getObjectFactory().createGenericQuery(RCProductInStockEvent.class,"select e from com.shrct.businessprocess.purchase.impl.RCProductInStockEventImpl as e   where ((e.orderItem) = (:this)) and  e.active = 1      ").setParameter("this",this);
    Collection<RCProductInStockEvent> _list = query.list();
    final Function1<RCProductInStockEvent,Iterable<RCProductEntry>> _function = new Function1<RCProductInStockEvent,Iterable<RCProductEntry>>() {
        public Iterable<RCProductEntry> apply(final RCProductInStockEvent it) {
          RCProductEntry _product = it.getProduct();
          Iterable<RCProductEntry> _allRelatedProducts = _product.allRelatedProducts();
          return _allRelatedProducts;
        }
      };
    Iterable<Iterable<RCProductEntry>> _map = IterableExtensions.<RCProductInStockEvent, Iterable<RCProductEntry>>map(_list, _function);
    Iterable<RCProductEntry> _flatten = Iterables.<RCProductEntry>concat(_map);
    List<RCProductEntry> _list_1 = IterableExtensions.<RCProductEntry>toList(_flatten);
    return _list_1;
  }
  
  public static RCPurchaseOrderItem create(final RCPurchaseOrder purchaseOrder, final IObjectFactory objectFactory) {
    com.shrct.businessprocess.purchase.RCPurchaseOrderItem rCPurchaseOrderItem = new com.shrct.businessprocess.purchase.impl.RCPurchaseOrderItemImpl(
    	purchaseOrder
    );
    objectFactory.create(rCPurchaseOrderItem);
    return rCPurchaseOrderItem;			
    
  }
  
  public static RCPurchaseOrderItem createRCPurchaseOrderItemImpl(final RCPurchaseOrder purchaseOrder, final IObjectFactory objectFactory, final Procedure1<RCPurchaseOrderItem> init) {
    com.shrct.businessprocess.purchase.RCPurchaseOrderItem rCPurchaseOrderItem = new com.shrct.businessprocess.purchase.impl.RCPurchaseOrderItemImpl(
    	purchaseOrder
    );
    objectFactory.create(rCPurchaseOrderItem);
    init.apply(rCPurchaseOrderItem);
    
    return rCPurchaseOrderItem;			
    
  }
  
  public RCPurchaseOrderItemProxy toProxy() {
    com.shrct.businessprocess.purchase.proxy.RCPurchaseOrderItemProxy proxy = new com.shrct.businessprocess.purchase.proxy.RCPurchaseOrderItemProxy();
    proxy.setId(this.getId());
    if(this instanceof edu.fudan.mylang.pf.INamedModelObject){
    	proxy.setName(((edu.fudan.mylang.pf.INamedModelObject)this).getEntityName());
    }
    return proxy;
    
  }
}
